import sys
import cPickle as pickle
from collections import defaultdict
import os
import codecs
import difflib
import re

delim = "##"

class pickled_dict(object):
    def __init__(self, filename):        
        self.filename = filename
        if os.path.exists(filename):
            self.dict = pickle.load(file(filename,'rb'))
        else:
            self.dict = {}
            
    def __del__(self):
        pickle.dump(self.dict, file(self.filename,'wb'), pickle.HIGHEST_PROTOCOL)

def replace_all(s, chars, sep):
    r = s
    for ch in chars:
        r = r.replace(ch, sep)
    return r

autolisp_encoding = 'windows-1252'

def read_translations(translated_registy_filename, mydict):
    fn = translated_registy_filename
    for line in file(fn,"rt"):
        translation_filename = line.replace("\n",'')
        if not os.path.exists(translation_filename):
            print 'failed to open file ', line
        else:
            print 'reading ', translation_filename
            translation_file = codecs.open(translation_filename, encoding=autolisp_encoding)
            for translation_str in translation_file:
                ls = translation_str.strip().split(delim)
                if len(ls)==3 and len(ls[2])>0:
                    orig_token = ls[1]
                    translated_token = ls[2]
                    mydict[orig_token] = translated_token
                        
    print 'added %d translated strings to the translation memory' % len(mydict)
    return mydict
    
def main(argv):
    translated = []
    
    inp_filename = argv[1]

    
    translation_memory = pickled_dict('mydict.pickle')    
    skip_list = pickled_dict('skiplist.pickle')    

    if translation_memory.dict == {}:
        print 'mydict.pickle not found, creating dictionary:'
        translation_memory.dict = read_translations("translated.list", {})

    orig_tokens = translation_memory.dict.keys()
    
    mt_filename = inp_filename+'.machine-translated'
    outp = codecs.open(mt_filename, encoding = autolisp_encoding, mode ='w')
    num_found = 0
    num_total = 0
    num_fuzzy = 0
    num_left = 0
    skip_fuzzy = False
    number_regexp = re.compile(r"[+-]?\d+\.?\d*")
    manual_list = set()

    print 'console encoding: ', sys.getdefaultencoding()

    for line in codecs.open(inp_filename,encoding=autolisp_encoding):        
        L = line.strip().split(delim)
        ent_id = L[0]
        orig_token = L[1]
        
        num_total += 1
        write_as_is = False

        if orig_token in translation_memory.dict:        
            transl_token = translation_memory.dict[orig_token]
            T = "%(ent_id)s%(delim)s%(orig)s%(delim)s%(transl)s" % {'ent_id':ent_id, 
                'delim':delim, 'orig':orig_token, 'transl': transl_token}
            outp.write("%s\n" % T)
            num_found += 1

        elif orig_token in skip_list.dict:
            write_as_is = True

        elif orig_token in manual_list:
            write_as_is = True

        elif not skip_fuzzy:
            matches = difflib.get_close_matches(orig_token, orig_tokens, 3)

            if len(matches) == 0:
                write_as_is = True
                manual = True

            else:
                fmt_matches = ["\t%d) [%s]" % (i+1,m) for i,m in enumerate(matches)]
                print '\n[%s], fuzzy matches: \n%s' %(orig_token, '\n'.join(fmt_matches))
                ans = raw_input('''\n"1","2",.. to auto-replace numbers, 
"m" manually translate later, 
"n" never translate
"r" to replace, 
"a" to skip all fuzzies: ''')

                # skip all
                if ans == 'a': 
                    write_as_is = True
                    skip_fuzzies = True

                # do not translate
                elif ans == 'n': 
                    write_as_is = True
                    skip_list.dict[orig_token] = 1

                # manually translate later
                elif ans == 'm':
                    write_as_is = True
                    manual_list.add(orig_token)

                # replace
                elif ans == 'r': # replace
                    replace_pair = raw_input("replace-with,replace-what: ").split(',')
                    fuzzy_transl = translation_memory.dict[matches[0]].replace( replace_pair[1], replace_pair[0])
                    T = "%(ent_id)s%(delim)s%(orig)s%(delim)s+FUZZY+%(transl)s" % {'ent_id':ent_id, 
                        'delim':delim, 'orig':orig_token, 'transl': fuzzy_transl}

                    translation_memory.dict[orig_token] = fuzzy_transl

                    outp.write("%s\n" % T)
                    num_fuzzy += 1

                # replace numbers
                else:
                    v = int(ans)-1
                    if 0 <= v < len(matches):
                        orig_token_fuzzy_match = matches[v]
                        fuzzy_transl = translation_memory.dict[orig_token_fuzzy_match]
                        numbers_orig = re.findall(number_regexp, orig_token)
                        numbers_ref = re.findall(number_regexp, fuzzy_transl)
                        for n1, n2 in zip(numbers_orig, numbers_ref):
                            fuzzy_transl = fuzzy_transl.replace(n2, n1)

                        T = "%(ent_id)s%(delim)s%(orig)s%(delim)s+FUZZY+%(transl)s" % {'ent_id':ent_id, 
                            'delim':delim, 'orig':orig_token, 'transl': fuzzy_transl}

                        translation_memory.dict[orig_token] = fuzzy_transl

                        outp.write("%s\n" % T)
                        num_fuzzy += 1

        if write_as_is:
            num_left += 1
            try:
                sys.stdout.write('\n%15s written as-is\n'% orig_token[:15])
            except:
                pass
            if orig_token in manual_list:
                T = "%(ent_id)s%(delim)s%(orig)s%(delim)s%(transl)s" % {'ent_id':ent_id, 
                    'delim':delim, 'orig':orig_token, 'transl': 'MANUAL'}
                outp.write("%s\n" % T)
            else:
                outp.write(line)

        perc_matches = 100.0*num_found/num_total
        perc_fuzzy = 100.0*num_fuzzy/num_total
        perc_left = 100.0*num_left/num_total
        try:            
            progress = '%15s: total:%d dict:%d(%2.2f%%) fuzzy:%d(%2.2f%%) as-is:%d(%2.2f%%)\n' % (orig_token[:15],
                 num_total, 
                 num_found, perc_matches, 
                 num_fuzzy, perc_fuzzy,
                 num_left, perc_left)
            sys.stdout.write(progress)
        except:
            pass

    outp.close()
    want_rename = raw_input('\n\nDo you want to rename output file [%s] back to [%s]\nThis will delete original untranslated file [%s]? (Y/n) '%(mt_filename, inp_filename, inp_filename))
    if want_rename == 'Y':        
        os.remove(inp_filename)
        os.rename(mt_filename, inp_filename)
        if os.path.exists(inp_filename) and not os.path.exists(mt_filename):
            print '\nRenamed. Your auto-translated file: %s' % inp_filename
    else:
        print '\nYour auto-translated file: %s' % mt_filename            
    

if __name__ == '__main__':    
    argv = sys.argv
    main(argv)

